package com.angel.shiro;

import com.angel.bean.*;
import com.angel.config.MyConfig;
import com.angel.service.*;
import com.angel.utlis.GetIpUtli;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Collection;
import java.util.List;

/**
 * 管理员登录的ralm ，对应employee表
 *
 * @author Rabit
 */
public class SystemAdminAuthorizingRealm extends AuthorizingRealm {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private SysMenuService sysMenuService;

    @Autowired
    private EmployeeService employeeService;
    @Autowired
    private EmployeeTypeService employeeTypeService;
    @Autowired
    private OtherlogService otherlogService;

    @Autowired
    private IpListService ipListService;
    @Autowired
    private MyConfig myConfig;


    /**
     * 认证回调函数, 登录时调用 设置了authc才会进入
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UserNamePasswordToken token = (UserNamePasswordToken) authenticationToken;
//        如果是管理员登录则执行登录处理
        if (token.getUserType().equals("2")) {
            Employee employee = new Employee();
            employee.setLoginName(token.getUsername());
            employee.setPassword(new String(token.getPassword()));
            Employee et = employeeService.findOne(employee);
            EmployeeType employeeType = new EmployeeType();
            employeeType.setEmTypeId(et.getEmTypeId());
            List<EmployeeType> etList = employeeTypeService.findEmployeeType(employeeType);
            // 校验用户名密码
            if (et != null) {
                if (etList==null || etList.isEmpty()){
                    return null;
                }
                /*实现单用户登录*/
             //   String name = authenticationToken.getPrincipal();
                Object obj = authenticationToken.getPrincipal();
                //处理session
                DefaultWebSecurityManager securityManager = (DefaultWebSecurityManager) SecurityUtils.getSecurityManager();
                DefaultWebSessionManager sessionManager = (DefaultWebSessionManager)securityManager.getSessionManager();
                //获取当前已登录的用户session列表
                Collection<Session> sessions = sessionManager.getSessionDAO().getActiveSessions();
                for(Session session:sessions){
                    //清除该用户以前登录时保存的session
                   if(obj.equals(String.valueOf(session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY)))) {
                        sessionManager.getSessionDAO().delete(session);
                    }
                }


                this.logger.info("-------------" + et.getLoginName() + ":" + et.getEmName() + ":登录了");
                otherlogService.insertSelective(new Otherlog(et.getLoginName()+"登录",et.getEmId(),et.getBranchesId(),et.getEmName()));
                GetIpUtli getIpUtli = new GetIpUtli();
                IpList ipList = new IpList();
                ipList.setIp(token.getHost());
                ipList.setUserId(et.getEmId());
                ipList.setIpaddress(getIpUtli.getAdd(token.getHost(), myConfig.getAk()));
                ipList.setIpdate(new Timestamp(System.currentTimeMillis()));
                ipList.setReserve1("e");
                ipList.setReserve2(et.getLoginName());
                ipList.setReserve3(et.getEmName());
                ipListService.insertSelective(ipList);
                return new SimpleAuthenticationInfo(new Principal(et), et.getPassword(), getName());
            }
        }
        return null;
    }

    /**
     * 获取权限授权信息，如果缓存中存在，则直接从缓存中获取，否则就重新获取， 登录成功后调用
     */
    @Override
    protected AuthorizationInfo getAuthorizationInfo(PrincipalCollection principals) {
        if (principals == null) {
            return null;
        }
        //中这里可以设置缓存，从缓存中读取
        return doGetAuthorizationInfo(principals);
    }

    /**
     * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用
     *
     * @param principalCollection 用户信息
     * @return 令牌信息
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        Principal principal = (Principal) getAvailablePrincipal(principalCollection);

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //找到当前用户登录的角色

        EmployeeType employeeType = new EmployeeType();
        employeeType.setEmTypeId(principal.getEtype());
        //通过范围id获取角色，岗位便是角色
        List<EmployeeType> etList = employeeTypeService.findEmployeeType(employeeType);
//        Set<String> role = new HashSet<>();
        if (etList != null && etList.size() > 0) {
            for (EmployeeType et : etList) {
                info.addRole(et.getTypeName());
//                根据角色获取菜单对应的权限
                List<SysMenu> list = sysMenuService.findMenuByEtid(principal.getEtype());
                if (list != null && list.size() > 0) {
                    for (SysMenu sysMenu : list) {
                        info.addStringPermission(sysMenu.getHref());
                    }
                }
            }
            return info;
        }
        return null;
    }


    /**
     * 授权用户信息
     */
    public static class Principal implements Serializable {

        private static final long serialVersionUID = 6977402643848374753L;
        private int type;
        private Integer id;
        private String username;
        private String name;
        private Employee employee;
        //员工的岗位id
        private int etype;

        public Principal(Employee employee) {
            this.employee=employee;
            this.id = employee.getEmId();
            this.username = employee.getLoginName();
            this.name = employee.getEmName();
            this.etype = employee.getEmTypeId();
            this.type = 1;
        }

        public Employee getEmployee() {
            return employee;
        }

        public int getType() {
            return type;
        }

        public int getEtype() {
            return etype;
        }

        public Integer getId() {
            return id;
        }


        public String getName() {
            return name;
        }

        public String getUsername() {
            return username;
        }

        @Override
        public String toString() {
            return this.username;
        }
    }
}
